<?php
date_default_timezone_set('America/Los_Angeles');
switch(defined('UHU4_DEBUG_MODE'))
{
	case false:
		ini_set('display_errors','0');
	break;
	default:
		ini_set('display_errors','1');
	break;
}
define('NULL_KEY','00000000-0000-0000-0000-000000000000',true);
if(defined('UHU4_ROOT') === false)
{
	# Define the root directory for the UHU codebase
}
if(defined('UHU_LIBS') === false)
{
	# Define the directory where non-UHU library scripts (Smarty, Zend Framework etc) are held
}
if(defined('UHU4_APPS') === false)
{
	# Define the directory where UHU applications are held
	define('UHU4_APPS',UHU4_ROOT . '/apps');
}
if(function_exists('headerBySAPI') === false)
{
	function headerBySAPI()
	{
		$num_args = func_num_args();
		if($num_args === 0)
		{
			throw new Exception('No Arguments Passed');
		}
		$cgi = (substr(PHP_SAPI,0,3) === 'cgi');
		switch($cgi)
		{
			case true:
				$header = func_get_arg(0);
				if(substr($header,0,5) === 'HTTP/')
				{
					$header = substr_replace($header,'Status:',0,8);
				}
			default:
				$header = isset($header) ? $header : func_get_arg(0);
				switch($num_args)
				{
					case 1:
						return header($header);
					break;
					case 2:
						return header($header,func_get_arg(1));
					break;
					default:
						return header($header,func_get_arg(1),func_get_arg(2));
					break;
				}
			break;
		}
	}
}
if(function_exists('llXorBase64StringsCorrect') === false)
{
	function llXorBase64StringsCorrect($s1,$s2)
	{
		return uhu4::llXorBase64StringsCorrect($s1,$s2);
	}
}
if(function_exists('is_uuid') === false)
{
	function is_uuid($string)
	{
		return uhu4::is_uuid($string);
	}
}
if(function_exists('xmlrpc_query') === false)
{
	function xmlrpc_query($channel,$idata=0,$sdata='',$get_response=false)
	{
		uhu4::load_component('xmlrpc');
		$client = uhu4::xmlrpc('xmlrpc.secondlife.com','/cgi-bin/xmlrpc.cgi');
		$array['Channel'] = $channel;
		$array['IntValue'] = $idata;
		$array['StringValue'] = $sdata;
		if($client->query('llRemoteData',$array) === false)
		{
			headerBySAPI('HTTP/1.1 500 Internal Server Error');
			echo 'An error occurred - ',$client->getErrorCode(),':',$client->getErrorMessage();
			exit;
		}
		else
		{
			return $client->getResponse();
		}
	}
}
if(function_exists('llMD5String') === false)
{
	function llMD5String($string,$nonce=0)
	{
		return md5("$string:$nonce");
	}
}
if(function_exists('md52uuid') === false)
{
	function md52uuid($hash)
	{
		if(strlen($hash) !== 32)
		{
			return false;
		}
		else
		{
			return sprintf('%s-%s-%s-%s-%s',
				substr($hash,0,8),
				substr($hash,8,4),
				substr($hash,12,4),
				substr($hash,16,4),
				substr($hash,20)
			);
		}
	}
}
class uhu4_exception extends Exception
{
	public static $handler_params = array('uhu4_exception','handler');
	private $detailed;
	protected $errcontext;
	public function __construct($message,$code=NULL)
	{
		$num_args = func_num_args();
		switch($num_args)
		{
			default:
				parent::__construct($message,$code);
			break;
			case 5:
				$this->code       = func_get_arg(0);
				$this->message    = func_get_arg(1);
				$this->file       = func_get_arg(2);
				$this->line       = func_get_arg(3);
				$this->errcontext = func_get_arg(4);				
			break;
		}
		$this->detailed = defined('UHU4_DEBUG_MODE');
	}
	public function __toString()
	{
		if($this->detailed)
		{
			return $this->getFile() . ' had an error on line ' . $this->getLine() . ': ' . $this->getMessage();
		}
		else
		{
			return $this->getMessage();
		}
	}
	public function getException()
	{
		switch($this->getCode())
		{
			case null:
			case 0:
			case E_ERROR:
			case E_USER_ERROR:
				headerBySAPI('HTTP/1.1 500 Internal Server Error');
				die($this->__toString());
			break;
			default:
				print $this->__toString();
			break;
		}
	}
	public static function handler()
	{
		$num_args = func_num_args();
		switch($num_args)
		{
			case 0:
				throw new uhu4_exception('No arguments passed to handler',E_ERROR);
			break;
			case 5:
				$args = func_get_args();
				throw new uhu4_exception($args[0],$args[1],$args[2],$args[3],$args[4]);
				return true;
			break;
			default:
				$arg2 = func_get_arg(1);
			case 1:
				$arg1 = func_get_arg(0);
			break;
		}
		if($num_args === 1 && gettype($arg1) === 'object')
		{
			return $arg1->getMessage();
		}
		else
		{
			throw new uhu4_exception($arg2,$arg1);
		}
	}
}
if(defined('UHU4_NO_OVERRIDE') === false)
{
	set_exception_handler(uhu4_exception::$handler_params);
	set_error_handler(uhu4_exception::$handler_params);
}
class uhu4_components
{
	# uhu4 components are code that is typically used by several applications
	function __construct()
	{
		self::$components = array(
				'smarty'    => UHU4_ROOT . '/smarty.php',
			);
	}
	private static $components = array();
	private static $loaded_components = array();
	public static function load($label)
	{
		if(self::exists($label) === false)
		{
			throw new uhu4_exception('Component \'' . $label . '\' is unsupported');
		}
		else
		{
			switch(self::loaded($label))
			{
				case true:
					return true;
				break;
				default:
					require(self::$components[$label]);
					self::$loaded_components[$label] = true;
				break;
			}
		}
	}
	private static function exists($label)
	{
		return array_key_exists($label,self::$components);
	}
	private static function loaded($label)
	{
		return array_key_exists($label,self::$loaded_components);
	}
}
class uhu4_applications
{
	# uhu4 applications either build upon the uhu4 components, or consist of code solving a specific problem.
	private static $components = array();
	private static $loaded_components = array();
	function __construct()
	{
		self::$components = array( # See uhu4_components::_construct() for how to construct array
			);
	}
	public static function load($label)
	{
		if(self::exists($label) === false)
		{
			throw new uhu4_exception('Application \'' . $label . '\' is unsupported');
		}
		else
		{
			switch(self::loaded($label))
			{
				case true:
					return true;
				break;
				default:
					require(self::$components[$label]);
					self::$loaded_components[$label] = true;
				break;
			}
		}
	}
	private static function exists($label)
	{
		return array_key_exists($label,self::$components);
	}
	private static function loaded($label)
	{
		return array_key_exists($label,self::$loaded_components);
	}
}
class uhu4
{
	public static function load_components()
	{
		$num_args = func_num_args();
		if($num_args === 0)
		{
			throw new Exception('No Components Specified');
		}
		else
		{
			$args = func_get_args();
			foreach($args as $arg)
			{
				try
				{
					uhu4_components::load($arg);
				}
				catch(Exception $e)
				{
					headerBySAPI('HTTP/1.1 500 Internal Server Error');
					die('Could not load component \'' . $arg . '\':' . $e->getMessage());
				}
			}
			return true;
		}
	}
	public static function load_apps()
	{
		$num_args = func_num_args();
		if($num_args === 0)
		{
			throw new Exception('No Applications Specified');
		}
		else
		{
			$args = func_get_args();
			foreach($args as $arg)
			{
				try
				{
					uhu4_applications::load($arg);
				}
				catch(Exception $e)
				{
					headerBySAPI('HTTP/1.1 500 Internal Server Error');
					die('Could not load application \'' . $arg . '\':' . $e->getMessage());
				}
			}
			return true;
		}
	}
	public static function curl($url,$method='GET',$options=NULL,$vars=NULL,$add_info=NULL)
	{
		$options = empty($options) ? array() : $options;
		if(is_array($options) === true)
		{
			if(array_key_exists(CURLOPT_URL,$options) === false)
			{
				$options[CURLOPT_URL] = $url;
			}
			if(array_key_exists(CURLOPT_HEADER,$options) === false)
			{
				$options[CURLOPT_HEADER] = false;
			}
			if(array_key_exists(CURLOPT_FOLLOWLOCATION,$options) === false)
			{
				$options[CURLOPT_FOLLOWLOCATION] = 1;
			}
			if(array_key_exists(CURLOPT_RETURNTRANSFER,$options) === false)
			{
				$options[CURLOPT_RETURNTRANSFER] = 1;
			}
		}
		if ($method === 'POST')
		{
			$options[CURLOPT_POST] = 1;
			if(is_array($vars) === true)
			{
				$options[CURLOPT_POSTFIELDS] = $vars;
			}
		}
		$ch = curl_init();
		if(is_array($options) === true)
		{
			curl_setopt_array($ch,$options);
		}
		$obj = new stdClass;
		$obj->data = curl_exec($ch);
		if(is_array($options) === true && array_key_exists(CURLOPT_TIMEVALUE,$options) === true)
		{
			$obj->modtime = curl_getinfo($ch,CURLINFO_FILETIME);
		}
		if(is_array($add_info) === true)
		{
			$obj->info = array();
			foreach($add_info as $v)
			{
				$obj->info[$v] = curl_getinfo($ch,$v);
			}
		}
		if ($obj->data === false)
		{
			$obj->error = curl_error($ch);
		}
		curl_close($ch);
		return $obj;
	}
	public static function smarty_curl($url,$cache_lifetime=30,$file='body.tpl',$method='GET',$options=NULL,$vars=NULL,$add_info=NULL)
	{
		uhu4::load_components('smarty');
		switch($file)
		{
			case 'body.tpl':
			break;
			default:
				$file = 'body.tpl';
			break;
		}
		$cache_id = $url . '/' . $method . '-' . sha1(serialize($options)) . '-' . sha1(serialize($vars)) . '-' . sha1(serialize($add_info));

		$Smarty = Smarty_Registry::get(
				/* template directory. Not entirely sure if Smarty can cache stuff without an actual template file */,
				/* compile directory. Again, for this purpose it might be rather superfluous */ ,
				/* cache directory. Where the serialized uhu4::curl() response gets stored. */
			);
		$Smarty->caching = 1;
		$Smarty->cache_lifetime = $cache_lifetime;
		$Smarty->compile_check = true;
		if($Smarty->is_cached($file,$cache_id) === false)
		{
			$curl = uhu4::curl($url,$method,$options,$vars,$add_info);
			if(isset($curl->data))
			{
				switch($file)
				{
					case 'body.tpl':
						$Smarty->assign('body',serialize($curl));
					break;
				}
			}
			else
			{
				return $curl; // for when uhu4::curl() generally returns false, or otherwise reports an error.
			}
		}
		else
		{
			$curl = unserialize($Smarty->fetch($file,$cache_id));
		}
		return $curl;
	}
	public static function xmlrpc($server,$path=false,$port=80)
	{
		uhu4::load_components('xmlrpc');
		$client = new IXR_Client('xmlrpc.secondlife.com','/cgi-bin/xmlrpc.cgi');
		return $client;
	}
	public static function is_uuid($string)
	{
		return (bool)preg_match('/^([0-9a-f]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})$/',$string);
	}
	public static function llXorBase64StringsCorrect($s1,$s2)
	{
		if(strlen(base64_decode($s1)) > strlen(base64_decode($s2)))
		{
			$s2 = base64_encode(str_pad(base64_decode($s2),strlen(base64_decode($s1)),base64_decode($s2),STR_PAD_RIGHT));
		}
		return base64_encode(base64_decode($s1) ^ base64_decode($s2));
	}
	public static function stripslashes_keys(&$item,&$key)
	{
		$item      = self::stripslashes($item,$key);
		$key_type  = gettype($key);
		$key       = stripslashes($key);
		settype($key ,$key_type );
	}
	public static function stripslashes(&$item,$key)
	{
		$item_type = gettype($item);
		$item      = stripslashes($item);
		settype($item,$item_type);
	}
	public static function sanitize_keys(&$item,&$key,$pattern)
	{
		$item      = self::sanitize($item,$key,$pattern);
		$key_type  = gettype($key);
		$key       = preg_replace($pattern,'',$key);
		settype($key ,$key_type );
	}
	public static function sanitize(&$item,$key,$pattern)
	{
		$item_type = gettype($item);
		$item = preg_replace($pattern,'',$item);
		settype($item,$item_type);
	}
	public static function prep_for_explode(&$item,$key)
	{
		$item = trim(preg_replace('/[\s|,|\||;]+/',' ',$item));
	}
	public static function strtolower(&$item,$key)
	{
		$item = strtolower($item);
	}
	public static function urlencode_kv(&$item,&$key)
	{
		$key = urlencode($key);
		$item = urlencode($item);
	}
	public static function xhtml_mime_type()
	{
		if(isset($_SERVER['HTTP_ACCEPT']) && strstr($_SERVER['HTTP_ACCEPT'],'application/xhtml+xml') !== false)
		{
			header('Content-type:application/xhtml+xml;charset=utf-8;');
		}
		else
		{
			header('Content-type:text/html;charset=utf-8;');
		}
	}
}
new uhu4_components;
new uhu4_applications;
?>